
#include "HeFeng.h"

HeFeng::HeFeng() {}

/**********************************************************************************************************************
* 功能说明；  获取BILIBILI粉丝数
* 输入参数：  HeFengCurrentData *data     获取数据返回值
*             String id                   用户B站UID值
* 返回值：    无
**********************************************************************************************************************/
bool HeFeng::fans(HeFengCurrentData *data, String id) {  
  std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
  HTTPClient https;
  String url = "https://api.bilibili.com/x/relation/stat?vmid=" + id;
  client->setInsecure();
  Serial.print("[HTTPS] begin...bilibili\n");
  //开始连接并发送HTTP头
  if ( https.begin( *client , url ) ) {  // HTTPS
    //httpCode将在错误时为负
    int httpCode = https.GET();
    if ( httpCode > 0) {
      //// HTTP报头已经发送，服务器响应报头已经处理
      Serial.printf("[HTTPS] GET... code: %d\n", https.errorToString(httpCode).c_str());
      if ( httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY ) {
        //读取HTTP返回数据
        String payload = https.getString();
        Serial.printf("[HTTPS] fans payload:%s\n", payload.c_str());
        DynamicJsonDocument jsonBuffer(2048);
        deserializeJson(jsonBuffer, payload);
        JsonObject root = jsonBuffer.as<JsonObject>();
        uint32_t follower = root["data"]["follower"];
        data->follower = follower;
        data->Bilibili_Statue = 1;
      }
    } 
    else {
      Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      https.end();
      // data->follower = 0;
      data->Bilibili_Statue = 0;
      return 0;
    }
    https.end();
  } 
  else {
    Serial.printf("[HTTPS] Unable to connect\n");
    https.end();
    // data->follower = 0;
    data->Bilibili_Statue = 0;
    return 0;
  }
  return 1;
}
/**********************************************************************************************************************
* 功能说明；  获取当前天气信息
* 输入参数：  HeFengCurrentData *data     获取数据返回值
*             String key                  天气密钥
*             String location             查询天气的位置
* 返回值：    无
**********************************************************************************************************************/
bool HeFeng::doUpdateCurr(HeFengCurrentData *data, String key,String location) {  
  std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
  client->setInsecure();
  String url = "https://devapi.qweather.com/v7/weather/now?lang=en&location=" +location + "&key=" + key;
  Serial.printf("[HTTPS] doUpdateCurr begin...now url:%s\n", url.c_str());
  uint8_t *outbuf = NULL;
  size_t len = 0;
  bool result = HttpsGetUtils::getString(url.c_str(), outbuf, len);
  Serial.printf("result = %d, len = %d", result, len);

  if (outbuf && len) {
    Serial.printf("write to serial, buf = %x, len = %d\n", outbuf, len);
    Serial.println("parse json");
    DynamicJsonDocument doc(768);
    DeserializationError error = deserializeJson(doc, (char *)outbuf, len);
    if (error) {
      Serial.print(F("deserializeJson() failed: "));
      // Serial.println(error.f_str());
      return 0;
    }
    String httpCode = doc["code"].as<String>();  // "200"
    Serial.println("doUpdateCurr httpCode:" + httpCode);

    // httpCode will be negative on error
    if ( httpCode == "200" ) {
      data->tmp = doc["now"]["temp"].as<int>();         //温度，默认单位：摄氏度
      data->fl  = doc["now"]["feelsLike"].as<int>();    //体感温度，默认单位：摄氏度
      data->hum = doc["now"]["humidity"].as<int>();     //相对湿度，百分比数值
      String wind_sc = doc["now"]["windScale"];         //风力等级
      data->wind_sc = wind_sc;
      data->iconMeteoCon = doc["now"]["icon"];            //天气状况的图标代码，另请参考天气图标项目
      meteoconIcon = getMeteoconIcon(data->iconMeteoCon);
      // data->iconMeteoCon = meteoconIcon;
      String cond_txt = doc["now"]["text"];             //天气状况的文字描述，包括阴晴雨雪等天气状态的描述
      data->cond_txt = cond_txt;
      data->Weather_Statue = 1;
      Serial.printf("[HTTPS] doUpdateCurr tmp:%d, fl:%d, hum:%d, wind_sc:%s\n",
                    data->tmp, data->fl, data->hum, wind_sc.c_str());
    } else {
      Serial.printf("[HTTPS] GET... failed, error: %s\n",httpCode.c_str());
      data->Weather_Statue = 0;
      // data->tmp = -1;
      // data->fl = -1;
      // data->hum = -1;
      // data->wind_sc = "-1";
      // data->cond_txt = "no network";
      // data->iconMeteoCon = -1;  
      return 0;
    }
  } else {
    Serial.printf("[HTTPS] Unable to connect\n");
    data->Weather_Statue = 0;
    // data->tmp = -1;
    // data->fl = -1;
    // data->hum = -1;
    // data->wind_sc = "-1";
    // data->cond_txt = "no network";
    // data->iconMeteoCon = -1;
    return 0;
  }
  // meteoconIcon = getMeteoconIcon(data->iconMeteoCon);
  return 1;
}
/**********************************************************************************************************************
* 功能说明；  获取天气预报
* 输入参数：  HeFengCurrentData *data     获取数据返回值
*             String key                  天气密钥
*             String location             查询天气的位置
* 返回值：    无
**********************************************************************************************************************/
bool HeFeng::doUpdateFore(HeFengForeData *data, String key,String location) {  
  uint8_t *outbuf = NULL;
  size_t len = 0;
  String url ="https://devapi.qweather.com/v7/weather/3d?lang=en&location=" + location +"&key=" + key;

  std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
  client->setInsecure();
  
  Serial.printf("[HTTPS] begin...forecast url:%s\n", url.c_str());

  bool result = HttpsGetUtils::getString(url.c_str(), outbuf, len);
  Serial.printf("result=%d, len=%d", result, len);
  if (outbuf && len) {
    Serial.printf("write to serial, buf=%x, len=%d\n", outbuf, len);
    // Serial.write(outbuf, len);
    Serial.println("doUpdateFore parse json");
    DynamicJsonDocument doc(3072);
    DeserializationError error = deserializeJson(doc, (char *)outbuf, len);
    if (error) {
      Serial.print(F("deserializeJson() failed: "));
      // Serial.println(error.f_str());
      return 0;
    }
    String httpCode = doc["code"].as<String>();  // "200"

    Serial.println("doUpdateFore httpCode:" + httpCode);

    // httpCode will be negative on error
    if (httpCode == "200") {
      JsonObject root = doc.as<JsonObject>();
      for (int i = 0; i < 3; i++) {
        data[i].tmp_min = root["daily"][i]["tempMin"].as<int>();
        // data[i].tmp_min = tmp_min;
        data[i].tmp_max = root["daily"][i]["tempMax"].as<int>();
        // data[i].tmp_max = tmp_max;
        String datestr = root["daily"][i]["fxDate"];
        data[i].datestr = datestr.substring(5, datestr.length());
        data[i].iconMeteoCon = root["daily"][i]["iconDay"];
        // String meteoconIcon = getMeteoconIcon(cond_code);
        // data[i].iconMeteoCon = meteoconIcon;
        Serial.printf(
            "[HTTPS] doUpdateCurr tmp_min:%d, "
            "tmp_max:%d, datestr:%s, cond_code:%d\n",
            data[i].tmp_min, data[i].tmp_max, datestr.c_str(),
            data[i].iconMeteoCon );
        data->Weather_Statue_t = 1;
      }
    } else {
      // Serial.printf("[HTTPS] GET... failed, error: %s\n", httpCode);
      for (int i = 0; i < 3; i++) {
        data[i].tmp_min = -1;
        data[i].tmp_max = -1;
        data[i].datestr = "N/A";
        data[i].iconMeteoCon = 0;
      }
      data->Weather_Statue_t = 0;
      return 0;
    }
  } else {
    Serial.printf("[HTTPS] doUpdateFore Unable to connect\n");
    for (int i = 0; i < 3; i++) {
      data[i].tmp_min = -1;
      data[i].tmp_max = -1;
      data[i].datestr = "N/A";
      data[i].iconMeteoCon = 0; 
    }
    data->Weather_Statue_t = 0;
    return 0;
  }
  return 1;
}

int HeFeng::getMeteoconIcon(uint32_t cond_code) {  // 获取天气图标
  if (cond_code == 100 || cond_code == 150 || cond_code == 9006) { //晴天
    return 1;
  }
  if (cond_code == 999) { //未知
    return 0;
  }
  if (cond_code == 104) {  //阴天
    return 2;
  }
  if (cond_code == 500 || cond_code == 501 || cond_code == 509 || cond_code == 510 || 
      cond_code == 514 || cond_code == 515) {  //雾
    return 3;
  }
  if (cond_code == 503 || cond_code == 504 || cond_code == 507 || cond_code == 508) {   //沙尘
    return 4;
  }
  if (cond_code == 499 || cond_code == 901 || cond_code == 400 || cond_code == 408) {   //雪
    return 5;
  }
  if (cond_code == 103 || cond_code == 101 || cond_code == 102 || cond_code == 151 ||
      cond_code == 152 || cond_code == 153  ) {  //晴间多云
    return 6;
  }
  if (cond_code == 502 || cond_code == 511 || cond_code == 512 || cond_code == 513) {  //霾
    return 7;
  }
  if (cond_code == 302 || cond_code == 303 || cond_code == 300 || cond_code == 301  ) { //雷阵雨
    return 8;
  }
  if (cond_code == 305 || cond_code == 309 || cond_code == 314 || cond_code == 399) {  //小雨
    return 9;
  }
  if (cond_code == 306 || cond_code == 315 || cond_code == 317 || cond_code == 318) {  //中雨
    return 10;
  }
  if (cond_code == 307 || cond_code == 308 || cond_code == 310 || cond_code == 313 ||
      cond_code == 311 || cond_code == 312 || cond_code == 316 || cond_code == 317 || 
      cond_code == 318 || cond_code == 350 || cond_code == 351) {   //暴雨
    return 11;
  }
  if (cond_code == 407) {  //	阵雪
    return 12;
  }
  if (cond_code == 401 || cond_code == 402 || cond_code == 403 ||
      cond_code == 409 || cond_code == 410) {   //中雪
    return 13;
  }
  if (cond_code == 304 || cond_code == 313 || cond_code == 404 ||
      cond_code == 405 || cond_code == 406) {   //雨雪天气
    return 14;  
  }
  return 0;
}

